package process

import (
	"crypto/md5"
	"dmsv/uuid"
	"fmt"
	"github.com/beego/beego/v2/core/logs"
	"io"
	"strconv"
	"time"
)

var (
	gUUIDCreate *uuid.IdWorker
	gDsid       int
)

type CallResult int

const (
	CALL_RESULT_SUCCESS CallResult = 0
	CALL_RESULT_FAIL    CallResult = 1
)

const (
	callbackNotify   = "/billing/voiceNotifyBilling"
	callbackVerify   = "/billing/voiceVerifyBilling"
	callbackCallback = "/billing/callBillingEnd"
	callbackDtmf     = "/billing/callDtmf"
	gKey             = "dkjfh3kdj34JHkf"
	callTypeNotify   = "2"
)

type errCode struct {
	Code    string `json:"code"`
	Answer  bool   `json:"answer"`
	Message string `json:"message"`
}

var (
	errSystem          = errCode{"001", false, "系统错误"}
	errTTSreq          = errCode{"002", false, "TTS生成错误"}
	errTTSWrite        = errCode{"003", false, "TTS写入磁盘失败"}
	errTTSConvert      = errCode{"004", false, "TTS格式转换失败"}
	errReqTimeout      = errCode{"005", false, "HTTP请求超时"}
	errReqRespErr      = errCode{"006", false, "HTTP请求响应错误"}
	errPlayOver        = errCode{"100", true, "语音播放完成"}
	errCallerHangup    = errCode{"101", true, "主叫挂断"}
	errCalleeHangup    = errCode{"102", true, "被叫挂断"}
	errCancelByApi     = errCode{"103", false, "接口结束呼叫"}
	errCancelByCaller  = errCode{"104", false, "主叫取消呼叫"}
	errCallerUnreach   = errCode{"105", false, "主叫无法接通"}
	errCalleeUnreach   = errCode{"106", false, "被叫无法接通"}
	errCallerRefuse    = errCode{"107", false, "主叫拒接"}
	errCalleeRefuse    = errCode{"108", false, "被叫拒接"}
	errCallerUnAnswer  = errCode{"109", false, "主叫无人接听"}
	errCalleeUnAnswer  = errCode{"110", false, "被叫无人接听"}
	succDtmfHangup     = errCode{"120", true, "用户按键结束"}
	errCallTimeout     = errCode{"205", false, "通话超时"}
	errCallerLineErr   = errCode{"400", false, "主叫线路禁止"}
	errCalleeLineErr   = errCode{"401", false, "线路禁止"}
	errCallerEnQueue   = errCode{"402", true, "入队失败"}
	errCallerBlack     = errCode{"403", false, "主叫黑名单"}
	errRecorderr       = errCode{"501", true, "录音失败"}
	errNoFile          = errCode{"502", true, "放音文件不存在"}
	errPlayFile        = errCode{"503", true, "放音失败"}
	errGetDtmf         = errCode{"504", true, "获取按键失败"}
	errServiceBusy     = errCode{"601", true, "坐席忙"}
	errServiceNoAnswer = errCode{"602", true, "坐席未接"}
	errServiceUnreach  = errCode{"603", true, "坐席无法接通"}
	errServiceAllBusy  = errCode{"604", true, "坐席全忙"}
	errQueueFull       = errCode{"605", true, "队列已满"}
	errServiceNotSign  = errCode{"606", true, "坐席未签入"}
	errSipNotExist     = errCode{"607", true, "sip账号不存在"}
	errSipNotReg       = errCode{"608", true, "sip电话未上线"}
	succCallerHangup   = errCode{"801", true, "接听,主叫挂机"}
	succCalleeHangup   = errCode{"802", true, "接听,坐席挂机"}
)

type response struct {
	TimeStamp  string `json:"timestamp"`
	Sign       string `json:"sig"`
	CallId     string `json:"callId"`
	Result     int    `json:"callResult"`
	AnswerTime string `json:"calledPickTime"`
	StatusCode string `json:"disconnectValue"`
	CallTime   int    `json:"callTime"`
}

func createSign(timeStamp string) string {

	signStr := timeStamp + gKey

	w := md5.New()
	io.WriteString(w, signStr)

	return fmt.Sprintf("%x", w.Sum(nil))
}

func createRecordName(callId, caller, callee string) string {

	data := time.Now().Format("20060102")
	dir := "/data/record/" + data

	return fmt.Sprintf("%s/%s-%s-%s.wav", dir, callId, caller, callee)

}

type detail struct {
	Caller     string `json:"caller"`
	Callee     string `json:"callee"`
	ServiceId  string `json:"serviceId"`
	IsPstn     bool   `json:"isPstn"`
	CallTime   string `json:"callTime"`
	AnswerTime string `json:"answerTime"`
	Dutation   int    `json:"dutation"`
	SipCode    string `json:"sipCode"`
}

type billEvent struct {
	Event     string   `json:"event"`
	CallId    string   `json:"callId"`
	CallStart string   `json:"startTime"`
	CallEnd   string   `json:"endTime"`
	Caller    string   `json:"caller"`
	Callee    string   `json:"callee"`
	TimeStamp string   `json:"timeStamp"`
	Result    errCode  `json:"result"`
	Record    string   `json:"record"`
	Detail    []detail `json:"detail"`
}

type AppBasicConfig struct {
	Arrange     bool `json:"arrange"`     //整理开关
	ArrangeTime int  `json:"arrangeTime"` //整理时间
	BindModel   bool `json:"bindModel"`   //是否熟客优先 true:是 ; false: 否
	AutoAnswer  bool `json:"autoAnswer"`  //接入来电模式 true:手动接听;false:自动接听
	ErrPass     bool `json:"errPass"`     //呼叫开启示忙  true: 开启;false:不开启
	ErrNo       int  `json:"errNumber"`   //未接次数
}

func sendResultGet(callBack, callId, answerTime, recordUrl string, callResult CallResult, callTime int, errInfo errCode) {
	/*
		TimeStamp  string `json:"timestamp"`
		Sign       string `json:"sig"`
		CallId     string `json:"callId"`
		Result     int    `json:"callResult"` // 0为成功，1为失败
		AnswerTime string `json:"calledPickTime"`
		StatusCode string `json:"disconnectValue"`
		CallTime   int    `json:"callTime"`
	*/
	// 成功就会计费，这里暂时仅根据计费情况判断，后续根据实际呼叫情况进行反馈
	if callTime > 0 {
		callResult = 0
	} else {
		callResult = 1
	}

	timeStamp := fmt.Sprintf("%d", time.Now().UnixNano()/1e6)
	signStr := createSign(timeStamp)
	url := fmt.Sprintf("%s?sig=%s&timestamp=%s&callId=%s&callResult=%d&calledPickTime=%s&disconnectValue=%s&callTime=%d&recordUrl=%s",
		callBack, signStr, timeStamp, callId, callResult, answerTime, errInfo.Code, callTime, recordUrl)

	receive, err := httpClient.Get(url)
	if err != nil {
		logs.Error("send to host:%v,failed:%v.", callBack, err)
	}
	logs.Debug("request url:%v,receive:%v", url, string(receive))
}

func sendErrResponseGet(callBack, callId string, errInfo errCode) {

	timeStamp := fmt.Sprintf("%d", time.Now().UnixNano()/1e6)
	signStr := createSign(timeStamp)
	url := fmt.Sprintf("%s?sig=%s&timestamp=%s&callId=%s&callResult=%d&calledPickTime=%s&disconnectValue=%s&callTime=%d",
		callBack, signStr, timeStamp, callId, 1, "00000", errInfo.Code, 0)

	receive, err := httpClient.Get(url)
	if err != nil {
		logs.Error("send to host:%v,failed:%v.", callBack, err)
	}
	logs.Debug("request url:%v,receive:%v", url, string(receive))
}

func sendDtmfGet(callId, devId, dtmf, callType string) {
	/*
		TimeStamp  string `json:"timestamp"`
		Sign       string `json:"sig"`
		CallId     string `json:"callId"`
		Result     int    `json:"callResult"` // 0为成功，1为失败
		AnswerTime string `json:"calledPickTime"`
		StatusCode string `json:"disconnectValue"`
		CallTime   int    `json:"callTime"`
	*/

	uri := gCallBack + callbackDtmf
	timeStamp := fmt.Sprintf("%d", time.Now().UnixNano()/1e6)
	signStr := createSign(timeStamp)
	url := fmt.Sprintf("%s?sig=%s&timestamp=%s&callId=%s&calltype=%s&dtmf=%s&developerId=%s",
		uri, signStr, timeStamp, callId, callType, dtmf, devId)

	receive, err := httpClient.Get(url)
	if err != nil {
		logs.Error("send to host:%v,failed:%v.", url, err)
	}
	logs.Debug("request url:%v,receive:%v", url, string(receive))
}

func createUUid() string {

	/* 组件标示 + 时间 + 随机数 + 业务 */
	timeStr := time.Now().Format("20060102150405")

	d := strconv.FormatInt(gUUIDCreate.NextId(), 16)

	return fmt.Sprintf("%d-%s-%s", gDsid, timeStr, d)
}
